package com.iccaplayer.sequencer;

import com.iccaplayer.midi.MidiPlay;

import android.content.Context;
import android.util.Log;

public class Sequencer {
	private final String TAG = "Sequencer";	
	
	private int samples;		// number of samples
	private int totalBeats;
	private int beats;	// number of beats
	private int bpm;	

	private Context context;
	private Matrix matrix;
	
	private MidiPlay midiPlayer;
	private Runnable playback;
	private boolean playing = false;
	private int count;
	
	private OnBPMListener mOnBPMListener;
	
	/**
	 * This method is called every time there's a new beat.
	 **/
	public interface OnBPMListener {
		public void onBPM(int beatCount, boolean isPlaying);
	}

	public Sequencer(Context ctx, MidiPlay midi) {
        this(ctx, midi,  5, 20, 120);
    }
	
	public Sequencer(Context ctx, MidiPlay midi, int nSamples, int nBeats, int bpm){
		context = ctx;
		midiPlayer = midi;
		samples = nSamples;
		totalBeats = nBeats;
		beats = 20;
		count = 0;
		this.bpm = bpm;
		matrix = new Matrix(context, samples, totalBeats);
	}
	
	public void setSamples(int nSamples){
		samples = nSamples;
	}
	
	public int getSamples(){
		return samples;
	}
	
    /**
     * Set a cell to enabled.
     **/
    public void enableCell(int sampleId, int beatId) {
        matrix.setCellValue(sampleId, beatId, true);
    }

    /**
     * Set a cell to enabled.
     **/
    public void disableCell(int sampleId, int beatId) {
        matrix.setCellValue(sampleId, beatId, false);
    }
    
    public void setCellEnabled(int sampleId, int beatId, Boolean value){
    	matrix.setCellValue(sampleId, beatId, value);
    }
    
    public Boolean getCellEnabled(int sampleId, int beatId){
    	return matrix.getCellValue(sampleId, beatId);
    }
    
    public void setCellKey(int sampleId, int beatId, String key){
    	matrix.setCellKey(sampleId, beatId, key);
    	getCellKeyText(sampleId, beatId);
    }
    
    public void setCellRowKey(int sampleId, String key){
    	for(int beatPos=0; beatPos<beats; beatPos++){
    		if(matrix.getCellValue(sampleId, beatPos)){
    			matrix.setCellKey(sampleId, beatPos, key);
    		}
    	}
    }
    
    public String getCellKey(int sampleId, int beatId){
    	return matrix.getCellKey(sampleId, beatId);
    }
	
    public String getCellKeyText(int sampleId, int beatId){
    	String key, result;
    	String pitches, octave;
    	
    	result = "";
    	key = matrix.getCellKey(sampleId, beatId);
    	
    	if(key != null){
    		if(key.length() > 2){
    			pitches = key.substring(0, 2);
    			octave = key.substring(2);		
    			result = octave + "/" + pitches;
    		}
    		else{					
    			pitches = key.substring(0,1);
    			octave = key.substring(1);
    			result = octave + "/" + pitches;
    		}		
    	}    	    	
    	
    	return result;
    }
    
	public void setOnBPMListener(OnBPMListener l) {
        this.mOnBPMListener = l;
    }

    public int getBpm() {
        return bpm;
    }

    public void setBpm(int bpm) {
        this.bpm = bpm;
    }

//    public void addColumns(int nCol) {
//    	matrix.growCells(nCol);
//        this.beats = this.beats + nCol;
//    }
//
//    public void deleteColumns(int nCol) {
//    	matrix.shrinkCells(nCol);
//        this.beats = this.beats - nCol;
//    }
    
    public void setPlaying(Boolean isPlaying, int playingPos){
    	playing = isPlaying;
    	if(playing){
    		play(playingPos);
    	}
    }
    
    public boolean isPlaying(){
    	return playing;
    }
    
    public void setBeats(int nBeats){
    	Log.d(TAG, "Set Beats: " + beats);
    	beats = nBeats;
    }
    
    public int getCount(){
    	return count;
    }

    public void play(int playPos) {
        // play sound periodically
    	count = playPos;
        playback = new Runnable() {
//            int count = 0;

            public void run() {
                while (playing) {
                    if (mOnBPMListener != null)
                        mOnBPMListener.onBPM(count, playing);
                    long millis = System.currentTimeMillis();
                    for (int i = 0; i < samples; i++) {                    	
                        if (matrix.getCellValue(i, count) == true && matrix.getCellKey(i, count) != null){
                        	midiPlayer.play(matrix.getCellKey(i, count));
                        }
                    }
                    
                    // infinite play
                    Log.d(TAG, "PlayCounts: " + count);
                    count = (count + 1) % beats;
                    long next = (60 * 1000) / bpm;
                    try {
                        Thread.sleep(next - (System.currentTimeMillis() - millis));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        if(playing){
            Thread thandler = new Thread(playback);
            thandler.start();       	
        }
    }
//
//    /**
//     * Stop the playback.
//     */
    public void stop() {
        playing = false;
    }
//
//    /**
//     * Toggle the reproduction++++++++++++++++++
//     */
    public void toggle() {
        if (playing) {
            stop();
            playing = false;
        } else {
            play(0);
            playing = true;
        }
    }
}
